package pl.iachoo.ctl.tabory.ui.editors.users;

import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import pl.iachoo.ctl.tabory.dao.api.services.IUserService;
import pl.iachoo.ctl.tabory.dao.data.vo.UserVO;
import pl.iachoo.ctl.tabory.dao.hibernate.services.ServiceManager;
import pl.iachoo.ctl.tabory.ui.base.EditorStateSL;
import pl.iachoo.ctl.tabory.ui.base.masterdetail.AbstractMasterSectionPart;
import pl.iachoo.ctl.tabory.ui.properties.Messages;
import pl.iachoo.ctl.tabory.ui.selection.ISelectionListener;

public class UserMasterSectionPart extends
		AbstractMasterSectionPart<UserSelection> {

	private final static Logger logger = Logger
			.getLogger(UserMasterSectionPart.class);

	private boolean isToolBarVisible;
	private boolean isFilterVisible;

	private ISelectionListener<UserSelection> selectionListener;

	private Section filterSection;
	private UserNameFilter userNameFilter;
	private UserLogonFilter userLogonFilter;
	private Text filterUserLogon;
	private Text filterUserName;

	public UserMasterSectionPart(Composite parent, FormToolkit toolkit,
			int style, String sectionName, boolean isToolBarVisible,
			boolean isFilterVisible) {
		super(parent, toolkit, style, sectionName);
		this.isFilterVisible = isFilterVisible;
		this.isToolBarVisible = isToolBarVisible;
		initGui(parentSection, toolkit);
		postInitGui(parentSection, toolkit);
		initActions();
	}

	@Override
	public UserSelection getSelection() {
		return selection;
	}

	@Override
	public void setSelection(UserSelection selection) {
		this.selection = selection;
		refreshToolBar();
		if (selection.getEditorStateSL().equals(EditorStateSL.CLEAN)) {
			setEnabled(true);
		} else {
			setEnabled(false);
		}
		tableViewer.setInput(selection.getListAllUsers());
	}

	@Override
	public void addSelectionListener(ISelectionListener<UserSelection> listner) {
		this.selectionListener = listner;
	}

	@Override
	public void removeSelectionListener(
			ISelectionListener<UserSelection> listner) {

	}

	@Override
	protected void initGui(Section parentSection, FormToolkit toolkit) {
		toolBar = getToolBar(parentSection, toolkit);
		parentSection.setTextClient(toolBar);
		toolBar.setVisible(isToolBarVisible);

		Composite container = toolkit.createComposite(parentSection);
		GridLayoutFactory.fillDefaults().numColumns(1).applyTo(container);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(true, true).applyTo(container);
		parentSection.setClient(container);

		tableViewer = new TableViewer(container, SWT.BORDER
				| SWT.FULL_SELECTION);
		table = tableViewer.getTable();
		table.setHeaderVisible(true);

		TableColumn columnUserName = new TableViewerColumn(tableViewer,
				SWT.NONE).getColumn();
		columnUserName.setWidth(120);
		columnUserName.setText(Messages
				.getString("users.editor.master.table.col0"));

		TableColumn columnUserLogon = new TableViewerColumn(tableViewer,
				SWT.NONE).getColumn();
		columnUserLogon.setWidth(120);
		columnUserLogon.setText(Messages
				.getString("users.editor.master.table.col1"));

		tableViewer.setLabelProvider(new TableLabelProvider());
		tableViewer.setContentProvider(new TableContentProvider());
		tableViewer.setSorter(new TableViewerSorter());
		tableViewer.addFilter(userNameFilter = new UserNameFilter());
		tableViewer.addFilter(userLogonFilter = new UserLogonFilter());

		toolkit.paintBordersFor(table);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(true, true).applyTo(table);

		filterSection = toolkit.createSection(container, Section.TWISTIE
				| Section.TITLE_BAR);
		GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5)
				.applyTo(filterSection);
		toolkit.paintBordersFor(filterSection);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(false, false).applyTo(filterSection);

		Composite filterComposite = toolkit.createComposite(filterSection);
		filterSection.setText(Messages.getString("common.filter"));
		toolkit.paintBordersFor(filterComposite);
		filterSection.setClient(filterComposite);
		GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2)
				.applyTo(filterComposite);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(false, false).applyTo(filterComposite);

		Label filterUserNameLabel = toolkit
				.createLabel(filterComposite, Messages
						.getString("users.editor.master.filter.filterusername"));
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.grab(true, true).applyTo(filterUserNameLabel);
		filterUserName = toolkit.createText(filterComposite, null);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.hint(100, SWT.DEFAULT).grab(true, true)
				.applyTo(filterUserName);
		Label filterUserLogonLabel = toolkit
				.createLabel(
						filterComposite,
						Messages.getString("users.editor.master.filter.filteruserlogon"));
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.grab(true, true).applyTo(filterUserLogonLabel);
		filterUserLogon = toolkit.createText(filterComposite, null);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
				.hint(100, SWT.DEFAULT).grab(true, true)
				.applyTo(filterUserLogon);
		toolkit.adapt(filterComposite, true, true);
		filterSection.setVisible(isFilterVisible);
	}

	@Override
	protected void postInitGui(Section parentSection, FormToolkit toolkit) {
	}

	@Override
	protected void initActions() {
		filterUserName.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				userNameFilter.setPattern(filterUserName.getText());
				tableViewer.refresh();
			}
		});
		filterUserLogon.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				userLogonFilter.setPattern(filterUserLogon.getText());
				tableViewer.refresh();
			}
		});
		tableViewer
				.addSelectionChangedListener(new ISelectionChangedListener() {
					@Override
					public void selectionChanged(SelectionChangedEvent event) {
						logger.debug("Table selection changed");
						IStructuredSelection tableSelection = (IStructuredSelection) event
								.getSelection();
						UserVO selectedUser = (UserVO) tableSelection
								.getFirstElement();
						selection.setSelectedUser(selectedUser);
						selectionListener.selectionChanged(selection);
					}
				});
		toolItemNew.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				selection.setEditorStateSL(EditorStateSL.NEW);
				selection.setSelectedUser(null);
				selectionListener.selectionChanged(selection);
			}
		});
		toolItemEdit.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				selection.setEditorStateSL(EditorStateSL.EDITING);
				selectionListener.selectionChanged(selection);
			}
		});
		toolItemDelete.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				try {
					IUserService userService = ServiceManager.getUserService();
					UserVO selectedUser = selection.getSelectedUser();
					boolean openConfirm = MessageDialog.openConfirm(
							getSection().getShell(),
							Messages.getString("users.editor.questions.delete.title"),
							Messages.getString("users.editor.questions.delete.message"));
					if (openConfirm) {
						userService.deleteUser(selectedUser);
						selection.setListAllUsers(userService.getAllUsers());
						selection.setSelectedUser(null);
						selectionListener.selectionChanged(selection);
					}
				} catch (Exception ex) {
					logger.error(ex.getMessage(), ex);
				}
			}
		});

	}

	@Override
	protected void setEnabled(boolean isEnabled) {
		super.setEnabled(isEnabled);
		filterSection.setEnabled(isEnabled);
	}

	protected void refreshToolBar() {
		if (selection.getSelectedUser() == null) {
			toolItemNew.setEnabled(true);
			toolItemEdit.setEnabled(false);
			toolItemDelete.setEnabled(false);
		} else {
			toolItemNew.setEnabled(true);
			toolItemEdit.setEnabled(true);
			toolItemDelete.setEnabled(true);
		}
	}

	private class TableLabelProvider extends LabelProvider implements
			ITableLabelProvider {

		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		public String getColumnText(Object element, int columnIndex) {
			UserVO user = (UserVO) element;
			switch (columnIndex) {
			case 0:
				return user.getUserName();
			case 1:
				return user.getUserLogon();
			default:
				return user.toString();
			}
		}
	}

	private class TableContentProvider implements IStructuredContentProvider {

		@SuppressWarnings("unchecked")
		public Object[] getElements(Object inputElement) {
			List<UserVO> list = (List<UserVO>) inputElement;
			return list.toArray();
		}

		public void dispose() {
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private class TableViewerSorter extends ViewerSorter {
		@Override
		public int compare(Viewer viewer, Object e1, Object e2) {
			UserVO v1 = (UserVO) e1;
			UserVO v2 = (UserVO) e2;
			return super.compare(viewer, v1.getUserLogon(), v2.getUserLogon());
		}
	}

	private class UserNameFilter extends ViewerFilter {

		private String patter;

		public void setPattern(final String pattern) {
			this.patter = pattern;
		}

		@Override
		public boolean select(Viewer viewer, Object parentElement,
				Object element) {
			if (patter == null || patter.length() == 0) {
				return true;
			}
			UserVO user = (UserVO) element;
			if (user.getUserName().contains(patter)) {
				return true;
			}
			return false;
		}

	}

	private class UserLogonFilter extends ViewerFilter {

		private String patter;

		public void setPattern(final String pattern) {
			this.patter = pattern;
		}

		@Override
		public boolean select(Viewer viewer, Object parentElement,
				Object element) {
			if (patter == null || patter.length() == 0) {
				return true;
			}
			UserVO user = (UserVO) element;
			if (user.getUserLogon().contains(patter)) {
				return true;
			}
			return false;
		}

	}

}
